package com.own.component.common.util.list;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * TreeNode
 *
 * @author chenxueli
 * @date 2024-03-31 14:23:00
 */
@Getter
@Setter
@NoArgsConstructor
public class TreeNode<T> implements Serializable {

    @Schema(title = "项目内容")
    private T item;

    @Schema(title = "子节点")
    private List<TreeNode<T>> children;

    public TreeNode(T item) {
        this.item = item;
    }

    /**
     * 获取树形列表数据
     *
     * @param list       原列表
     * @param idKey      标识上下级的key
     * @param fkIdKey    标识引用的键的key
     * @param <TREE_VO>  对象类型
     * @param <KEY_TYPE> 键的类型
     * @return 新列表信息
     */
    public static <TREE_VO, KEY_TYPE> List<TreeNode<TREE_VO>> build(
            List<TreeNode<TREE_VO>> list,
            Function<TREE_VO, KEY_TYPE> idKey,
            Function<TREE_VO, KEY_TYPE> fkIdKey
    ) {
        if (list.isEmpty()) {
            return new ArrayList<>();
        }
        // 根据相关信息转成对应的map
        var parentMap = list.stream().collect(Collectors.toMap(item -> idKey.apply(item.getItem()), Function.identity(), (v1, v2) -> v1));
        // 遍历所有的节点
        list.stream()
                // 过滤不包含在内的数据
                .filter(item -> parentMap.containsKey(fkIdKey.apply(item.getItem())))
                // 将所有的值赋值到上一级菜单中
                .forEach(item -> {
                    var parent = parentMap.get(fkIdKey.apply(item.getItem()));
                    var children = parent.getChildren();
                    if (children == null) {
                        var array = new ArrayList<TreeNode<TREE_VO>>();
                        array.add(item);
                        parent.setChildren(array);
                    } else {
                        children.add(item);
                    }
                });
        // 遍历筛选出父节点为根节点的内容
        return list.stream().filter(item -> fkIdKey.apply(item.getItem()) == null).collect(Collectors.toList());
    }

    /**
     * 递归检查数据
     *
     * @param list     列表
     * @param function 执行的方法
     * @param consumer 如果子节点全为false
     */
    public static <TREE_VO> boolean recurrenceCheck(
            List<TreeNode<TREE_VO>> list,
            Function<TREE_VO, Boolean> function,
            Consumer<TreeNode<TREE_VO>> consumer
    ) {
        if (list == null || list.isEmpty()) {
            return false;
        }
        var array = new ArrayList<Boolean>();
        for (var item : list) {
            // 如果包含有子节点，先处理子节点的数据
            var flag = false;
            if (item.getChildren() == null || item.getChildren().isEmpty()) {
                flag = recurrenceCheck(item.getChildren(), function, consumer);
            }
            if (!flag) {
                // 处理当前节点的数据
                flag = function.apply(item.getItem());
            }
            // 如果仍然为false，执行后续处理
            if (!flag) {
                consumer.accept(item);
            }
            array.add(flag);
        }
        return array.stream().anyMatch(Boolean::booleanValue);
    }

}
